home *** CD-ROM | disk | FTP | other *** search
- Title: STANDARD USAGE OF C LANGUAGE RECIO LIBRARY
- Copyright: (C) 1994 William Pierpoint
- Version: 2.00
- Date: April 15, 1994
-
-
-
- 1.0 INTRODUCTION
-
- The implementation descibed by this standard usage is a superset of the
- recio specification. Enhancements are noted in the text.
-
-
- 1.1 Mnemonics
-
- The recio functions have been given a consistent mnemonic naming
- convention. All recio functions are in lower case and start with
- the letter r. Function names are analogous to <stdio.h> functions.
- Mnemonics are as follows:
-
- Single letter (field functions) Multi-letter
- ---------------------------------------- -----------------
- b - base (prefix) beg - beginning
- c - column (prefix), character (suffix) ch - character
- d - double (suffix) col - column
- f - float (suffix) cxt - context
- i - integer (suffix) eof - end of file
- l - long (suffix) err - error
- n - number fld - field buffer
- r - record pointer (first letter) fn - function
- s - string pointer (suffix) no - number
- u - unsigned (suffix) rec - record buffer
- siz - size of buffer
- str - string
- txt - text
- 1.2 Order
-
- The order in which the prefix mnemonics appear indicates the order in which
- the arguments appear in the function. The suffix mnemonics of the input
- functions tell you what the function returns. The suffix mnemonics of the
- output functions indicate the last argument and tell you what the function
- outputs. All output functions return an integer with a zero value if the
- function executed successfully.
-
- For example, the input function rbgetui():
-
- arguments: r - record pointer
- b - base (radix) of input
- returns: ui - unsigned integer
-
- The output function rbputui():
-
- arguments: r - record pointer
- b - base (radix) of input
- ui - unsigned integer is output
-
- Note: c is used in the prefix of a function's name only once even if there are
- two column arguments. If the function inputs or outputs a character,
- there is only one column argument; otherwise there are two.
-
-
-
- 2.0 ERROR AND WARNING CHECKING
-
- The functions declared in the header <recio.h> make use of the errno macro
- defined in section 4.1.3 of ANSI X3.159-1989. This mechanism was chosen
- because (1) the <stdlib.h> conversion functions (strtod(), strtol(), etc.)
- make use of this error reporting mechanism and (2) the <recio.h> functions
- make use of the <stdlib.h> conversion functions.
-
- In this implementation, errno can return the following macro constants:
-
- 0 - No error.
- EACCES - permission denied.
- EINVAL - invalid argument (usually null record pointer).
- EMFILE - too many open files.
- ENOENT - no such file or directory.
- ENOMEM - out of memory.
-
- Beginning with version 1.1, recio functions set errno when the record
- pointer is invalid and set an internal error number when the record pointer
- is valid. The recio error number is accessed through the rerror function.
-
- The rerror function can return the following macro constants:
-
- 0 - No error.
- R_EINVAL - invalid argument (not the record pointer).
- R_EINVDAT - invalid data.
- R_EINVMOD - invalid mode.
- R_EMISDAT - missing data.
- R_ENOMEM - out of memory.
- R_ENOPUT - unable to write data to output.
- R_ERANGE - data out of range.
-
- Beginning with version 2.0, recio functions set an internal warning number
- when the record pointer is valid. The recio library never sets the warning
- number when the record pointer is invalid. The recio warning number is
- accessed through the rwarning function.
-
- The rwarning function can return the following macro constants:
-
- 0 - No warning.
- R_WEMPSTR - empty data string.
- R_WNOREG - unable to register exit function with atexit().
- R_WWIDTH - data too wide for columnar output.
-
-
- 2.1 Define Callback Error Function
-
- First define a callback error function to be used by the recio functions.
- You may give the function any name you wish. In the sample function below,
- the name rerrfn is used. The function takes one argument, a record pointer
- (REC *). It returns nothing (void). The function must first check for a
- valid record pointer using the risvalid function. Other than that, you can
- customize it to do whatever you want.
-
- The recio functions use a callback error function in order to give the
- most flexibility in handling errors. This rerrfn function just sends
- information to stderr. You may wish to send information to a printer,
- a file, a window, or a dialog box. You might even want to give users
- the ability to examine errors and enter corrections. If the error is
- corrected, you will want to call the rclearerr function before your
- callback error function returns.
-
- When your callback error function is invoked, check rerror() or errno
- to determine the cause of the error.
-
- Symbolic errno constants:
-
- * EACCESS means that you don't have permission to access this file. All
- MSDOS files have read permission.
-
- * EINVAL indicates an invalid argument to a function, usually a NULL record
- pointer. This resulted from a programming error.
-
- * EMFILE means the program tried to open more files than the maximum allotted
- by ROPEN_MAX or FOPEN_MAX. If your program is interactive, the user can
- close one or more open record streams. Or you might decide that ROPEN_MAX
- or FOPEN_MAX needs to be a larger value.
-
- * ENOENT says that ropen() could not find the requested file to open.
- Perhaps the name of the file was misspelled, or your program looked in
- wrong directory. If your program was trying to read a configuration file,
- it could use internal default values when the configuration file does
- not exist.
-
- * ENOMEM indicates that the program ran out of heap space. You may be able
- to correct this if you are able to deallocate memory you no longer need.
- For example, you could reduce the size of buffers when the size only
- affects speed. Such buffers need to be flushed first. Buffers used by
- the recio library do not fit this criteria.
-
- Symbolic rerror() constants:
-
- * R_EINVDAT says the data is invalid. Invalid data is caused by an
- unrecognized character in the field. For example, rgetui() doesn't
- expect to see a negative sign, so a negative number will be flagged as
- invalid data.
-
- * R_EINVMOD indicates that you opened a file in read mode, then used an output
- function or opened a file in write or append mode, then used an input
- function.
-
- * R_EMISDAT says the data is missing. Missing data means the field is empty.
- If you expect a number, you could substitute either zero or some unique
- number to indicate an empty field.
-
- * R_ENOMEM indicates that the program ran out of heap space. You may be able
- to correct this if you are able to deallocate memory you no longer need.
- For example, you could reduce the size of buffers when the size only
- affects speed. Such buffers need to be flushed first. Buffers used by
- the recio library do not fit this criteria.
-
- * R_ENOPUT says the program was unable to write the data to output. This
- could indicate that the disk is full.
-
- * R_ERANGE tells you that the data is outside the range of the function.
- For instance, suppose you used rgeti() to get an integer and the data
- value is 32768. If a 16-bit integer has an upper limit of 32767, the
- value is too large. If the data is wrong, you can have the error
- function correct it. If the data is right, you have to correct the
- data type in the program.
-
- The main purpose of this sample callback error function is to show some of
- kinds of things you can do in a callback error function. Note that when an
- error occurs, the column number indicator rcolno() has moved just beyond
- the error. To make it clearer to the user where the error occurred, rerrfn()
- displays rcolno()-1, but not less than rbegcolno(), the column number for the
- first column.
-
- A more detailed callback error function is given in the source code for the
- test program TESTCHG.C. The test program callback error function makes use
- of the rfix functions to fix up bad data (primarily overflows and underflows)
- and continue processing. If appropriate for your application, you can use
- these functions as well. They have been compiled into the recio libraries
- for your potential use.
-
- /* define callback error function */
- void rerrfn(REC *rp)
- {
- /* if rp is a valid record pointer */
- if (risvalid(rp)) {
-
- /* if reof indicator set */
- if (reof(rp)) {
- fprintf(stderr, "ERROR reading %s -- "
- "tried to read past end of file\n\n", rnames(rp));
-
- /* else rerror indicator set */
- } else {
-
- /* determine cause of error */
- switch (rerror(rp)) {
-
- /* input data errors */
- case R_ERANGE:
- case R_EINVDAT:
- case R_EMISDAT:
- /* output data errors */
- case R_ENOPUT:
-
- /* print location of error */
- fprintf(stderr, "DATA ERROR in FILE %s at LINE %ld,"
- " FIELD %u, COLUMN %u -- %s\n", rnames(rp), rrecno(rp),
- rfldno(rp), max(rcolno(rp)-1, rbegcolno(rp)), rerrstr(rp));
- break;
-
- /* non-fatal errors */
- case R_ENOREG:
- fprintf(stderr, "WARNING -- %s\n", rerrstr(rp));
- rclearerr();
- break;
-
- /* fatal errors (R_EINVMOD, R_EINVAL, R_ENOMEM) */
- default:
- fprintf(errout, "FATAL ERROR reading FILE %s -- %s\n",
- rnames(rp), rerrstr(rp));
- abort();
- break;
- }
- }
-
- /* else invalid record pointer */
- } else {
- switch (errno) {
-
- /* non-fatal errors */
- case EACCES:
- case EMFILE:
- fprintf(errout, "WARNING: %s\n", strerror(errno));
- break;
-
- /* fatal errors (EINVAL, ENOMEM) */
- default:
- fprintf(errout, "FATAL ERROR: %s\n", strerror(errno));
- abort();
- break;
- }
- }
- }
-
-
- 2.2 Define Callback Warning Function
-
- Next define a callback warning function. You may give the function any name
- you want. In the sample function below, the name rwarnfn is used. The
- function takes one argument, a record pointer (REC *). It returns nothing
- (void).
-
- The recio functions use a callback warning function in order to give the
- most flexibility in handling unusual conditions. For example, the recio
- library considers empty data strings to be legal but your application may
- want to flag an empty data string as a data error. You can do that by
- checking for R_WEMPSTR warnings in your callback warning function.
-
- When your callback warning function is invoked, check rwarning() to
- determine the cause of the warning.
-
- Symbolic warning constants:
-
- * R_WEMPSTR says that an empty data string was input. If you want to
- substitute another string, just use the rsetfldstr function to stuff the
- field buffer inside your callback warning function.
-
- * R_WWIDTH indicates that on output, the data will not fit between the
- columns specified. If the data is numeric, the recio output functions
- write asterisks to the output; if the data is a string, a truncated string
- is written.
-
- * R_WNOREG means the program was unable to register the internal recio exit
- function with the ANSI atexit() function. The internal recio exit
- function ensures that all open record streams are closed and all dynamic
- memory allocated by the recio library is deallocated.
-
- You can also use your callback warning function to keep track of the number
- of warnings, then print a summary of any warnings just before you close a
- record stream. You will find an example in the test program TESTCHP.C.
-
- void rwarnfn(REC *rp)
- {
- if (risvalid(rp)) {
- switch (rwarning(rp)) {
- case R_WNOREG: /* atexit() full */
- fprintf (errout, "WARNING %s\n", rwarnstr(rp));
- break;
- case R_WEMPSTR: /* empty data string */
- fprintf(errout, "WARNING reading %s at record %lu and field %u -- %s\n",
- rnames(rp), rrecno(rp), rfldno(rp), rwarnstr(rp));
- break;
- }
- }
- }
-
- 2.3 Register Callback Error and Warning Functions
-
- Once you have written your callback error and warning functions, you must let
- the other recio functions know that they exist. You use the rseterrfn and
- rsetwarnfn functions to register your callback functions.
-
- /* register callback error and warning functions */
- rseterrfn(rerrfn);
- rsetwarnfn(rwarnfn);
-
-
-
- 3.0 OPEN FILE
-
-
- 3.1 Open File and Get Record Pointer
-
- Use the ropen function to open the file you want to read, write, or append.
- Store the record pointer returned by the ropen function. Do not open recin,
- recout, recerr, or recprn (MSDOS printer). They are always open, so they do
- not need to be opened or closed.
-
- REC *rp = ropen("FILENAME.DAT", "r");
-
-
- 3.2 Check Record Pointer
-
- Following the ropen function, you need to check to see if the file was
- opened correctly. If ropen returned a NULL pointer, then the file was not
- opened.
-
- Errors other than ENOENT are reported to your callback error function.
- ENOENT is not reported since you may want to use default values if the
- data file is not available.
-
- /* if ropen() failed */
- if (!rp) {
- /* if it failed because file does not exist */
- if (errno==ENOENT) {
- /* action to take when file does not exist */
- ...
- }
- /* else ropen() succeeded */
- } else {
- /* set up stream (see sections 3.3 - 3.6) */
- ...
- /* read or write file (see sections 4 and 5) */
- ...
- /* close file (see section 6) */
- rclose(rp);
- }
-
-
- 3.3 Set Field and Text Delimiters
-
- The space character is the default value for both the field and text
- delimiters. The space character matches any white space. If you need to
- use something else, you need to explicitly set the values. Application
- maintenance will be easier if you always set the values.
-
- rsetfldch(rp, ','); /* set field delimiter character */
- rsettxtch(rp, '"'); /* set text delimiter character */
-
-
- 3.4 Set Field and Record Buffer Sizes
-
- Setting the field and record buffer sizes is optional. Buffers will be
- automatically reallocated as necessary. However if you set the field and
- record sizes in advance to the maximum value needed, you can reduce memory
- fragmentation. The field and record buffers are not used for output.
-
- rsetfldsiz(rp, 41); /* set size of field buffer */
- rsetrecsiz(rp, 133); /* set size of record buffer */
-
-
- 3.5 Set Context Number
-
- If your application opens record streams with more than one data format, you
- will want to set a context number. You use the context number so that your
- callback error function can determine (using the rcxtno function) which data
- format it is dealing with. Each context number must be a positive integer;
- zero and negative numbers are reserved. Predefined context symbolic
- constants are RECIN, RECOUT, RECERR, and (for MSDOS) RECPRN.
-
- #define SOILS_DB 1
- #define BUILDINGS_DB 2
-
- rsetcxtno(rp, SOILS_DB); /* set context number */
-
-
- 3.6 Set Beginning Column Number
-
- The first column number in the record buffer defaults to zero. If you prefer
- column numbering to start at one, use the rsetbegcolno function. It is mainly
- useful if using column delimited data. If a number takes up the first ten
- columns of the record, the column numbering will be 0 to 9 if rsetbegcolno()
- is set to 0, or 1 to 10 is rsetbegcolno() is set to 1.
-
- rsetbegcolno(rp, 1); /* first column is column 1 */
-
-
-
- 4.0 RECORD FUNCTIONS
-
- 4.1 The rgetrec Function
-
- If all the records in a data file have the same format, you will want to
- loop through all the records until the end of file is reached. If each
- record has a different format, you must call the rgetrec function each
- time you want to get the next record. Calling rgetrec() is optional for
- the first record.
-
- /* read all records in file */
- while (rgetrec(rp)) {
- /* Section 5 field functions go here ... */
- }
-
-
- 4.2 The rputrec Function
-
- After you write all the fields in one record, use the rputrec function
- to put the end-of-record newline character to the output and to reset the
- internal recio library variables for the next record.
-
- /* write end-of-record */
- rputrec(rp);
-
-
- 4.3 The rrecs Macro
-
- To get a pointer to the start of the record buffer, use the rrecs macro.
-
- /* echo record contents to stdout */
- printf("%s\n", rrecs(rp));
-
-
- 4.4 The rrecno Macro
-
- To get the record number, use the rrecno macro.
-
- /* echo record number and record contents to stdout */
- printf("%ld: %s\n", rrecno(rp), rrecs(rp));
-
-
-
- 5.0 GET AND PUT FIELD DATA
-
- 5.1 Field functions
-
- There are 48 functions that can be used to read or write data. A mnemonic
- system makes it easy to construct the name of any function you want. All you
- need to remember is that there are four prefixes, two bodies, and eight
- suffixes, and that the rb and rcb prefixes are used only with the i, l, ui,
- and ul suffixes.
-
- If the prefix contains the letter 'c', it is a column delimited field function.
- If the prefix contains the letter 'b', it is a field function that reads or
- writes an integral number in a specified base (radix). The eight suffixes
- indicate the eight data types: character, double, float, integer, long,
- string, unsigned integer, and unsigned long.
-
- Prefix Body Suffix Prefix Body Suffix
- ------ ---- ------ ------ ---- ------
- r get c rb get i
- rc put d rcb put l
- f ui
- i ul
- l
- s
- ui
- ul
-
-
- 5.2 The rskipfld Macro
-
- If your application does not need to read the data in a field, you can skip
- over the field by using the rskipfld macro.
-
- /* skip over a field */
- if (rskipfld(rp) != 1) printf("Unable to skip field.\n");
-
-
- 5.3 The rskipnfld Function
-
- If your application does not need to read the data in several adjacent
- fields, you can skip over the fields by using the rskipnfld function.
-
- /* skip over three fields */
- if (rskipnfld(rp, 3) != 3) printf("Unable to skip 3 fields.\n");
-
-
- 5.4 The reof Macro
-
- Use the reof macro to determine when the record stream has reached the
- end of file.
-
- /* if error or end of file reached */
- while (rgetrec(rp)) {
- ...
- }
- /* if end of file */
- if (reof(rp)) {
- ...
- /* else error */
- } else {
- ...
- }
-
-
- 5.5 The rerror Function
-
- Use the rerror function to determine if an error has occurred on a record
- stream. You can access a text string for the error using the rerrstr
- function.
-
- if (rerror(rp))
- printf("ERROR reading %s - %s\n",
- rnames(rp), rerrstr(rp));
- rclose(rp);
-
- It is a good practice to check for any errors just before closing
- a record stream. If the error indicator is clear, you have additional
- confidence that the stream was processed correctly.
-
-
- 5.6 The rseterr Function
-
- If you write wrapper functions or other functions that interact with
- recio functions, your code will need to handle errors. If can use
- the rseterr function to set the error number and to call the record
- stream callback error function.
-
- /* get integer and validate range */
- int rrgeti(REC *rp, int min, int max) {
- int result;
-
- result = rgeti(rp);
- if (result < min || result > max) {
- rseterr(rp, R_ERANGE);
- }
- return result;
- }
-
-
- 5.7 The rwarning Function
-
- Use the rwarning macro to determine if a warning has occurred on a record
- stream.
-
- if (rwarning(rp))
- printf("ERROR %s - %s\n", rnames(rp), rwarnstr(rp));
-
- It is good practice to check for any warnings just before closing an output
- record stream.
-
-
- 5.8 The rsetwarn Function
-
- If you write wrapper functions or other functions that interact with recio
- functions, you may need to provide warnings. The rsetwarn function sets the
- warning number and calls the record stream callback warning function.
-
- rsetwarn(rp, R_WWIDTH);
-
-
-
- 6.0 CLOSE FILE
-
- 6.1 Close File
-
- When finished reading or writing a data file, close it. Do not close recin,
- recout, recerr, or recprn as they are always open.
-
- /* close record file */
- rclose(rp);
-
-
- 6.2 Close All Files
-
- Rather than closing record files one at a time, one can close all open
- record files at once using the rcloseall function.
-
- /* all done */
- rcloseall();
-
-
-
- 7.0 REFERENCES
-
- 1. ANSI X3.159-1989, "American National Standard for Information Systems -
- Programming Language - C," American National Standards Institute,
- 11 West 42nd Street, New York, NY 10036, 1990.
-
-
- 8.0 INDEX
-
- errno macro ............ 2.0, 2.1, 3.2
- rbegcolno macro ........ 2.1
- rclearerr function ..... 2.1
- rclose function ........ 6.1
- rcloseall function ..... 6.2
- rcolno macro ........... 2.1
- rcxtno macro ........... 3.5
- recin expression ....... 3.1, 6.1
- reof macro ............. 2.1, 5.4
- rerror function ........ 2.1, 5.5
- rerrstr function ....... 2.1, 5.5
- rfix functions ......... 2.1
- rflds macro ............ 2.1
- rfldno macro ........... 2.1
- rbget functions ........ 5.1
- rbput functions ........ 5.1
- rcbget functions ....... 5.1
- rcbput functions ....... 5.1
- rcget functions ........ 5.1
- rcput functions ........ 5.1
- rget functions ......... 5.1
- rgetrec function ....... 4.1
- risvalid function ...... 2.1
- rnames macro ........... 2.1
- ropen function ........ 3.1
- rput functions ......... 5.1
- rrecs macro ............ 2.1, 4.3
- rrecno macro ........... 2.1, 4.4
- rsetbegcolno function .. 3.6
- rsetcxtno function ..... 3.5
- rseterr function ....... 5.6
- rseterrfn function ..... 2.3
- rsetfldch function ..... 3.3
- rsetfldsiz function .... 3.4
- rsetfldstr function .... 2.1
- rsetrecsiz function .... 3.4
- rsettxtch function ..... 3.3
- rsetwarn function ...... 5.8
- rsetwarnfn function .... 2.3
- rskipfld macro ........ 5.2
- rskipnfld function ..... 5.3
- rwarning function ...... 2.2, 5.7
- rwarnstr function ...... 2.2, 5.7
-